using System.Collections.Generic;
using System.Collections.ObjectModel;
using CodePlex.DnD4eCampaignManager.CampaignManagerTests.TestUtilities;
using CodePlex.DnD4eCampaignManager.DnD4e.Enums;
using CodePlex.DnD4eCampaignManager.DnD4e.Interfaces;
using CodePlex.DnD4eCampaignManager.Presentation;
using CodePlex.DnD4eCampaignManager.Presentation.ViewInterfaces;
using CodePlex.DnD4eCampaignManager.Repositories.Interfaces;
using NUnit.Framework;
using Rhino.Mocks;

namespace CodePlex.DnD4eCampaignManager.CampaignManagerTests.PresentationTests
{
    [TestFixture]
    public class MonsterPresenterTests
    {
        private const string MONSTER_NAME = "Something Nasty";
        private IMonster _monster;
        private MockRepository Mocks { get; set; }

        [Test]
        public void DisplayMonsterPopulatesTheViewFromTheMonsterRepository()
        {
            IMonsterRepository monsterRepository = Mocks.StrictMock<IMonsterRepository>();
            IMonsterView monsterView = Mocks.StrictMock<IMonsterView>();
            MonsterPresenter presenter = new MonsterPresenter(MONSTER_NAME, monsterView, monsterRepository);
            using ( Mocks.Record() )
            {
                LoadAndDisplayMonster(monsterView, monsterRepository);
            }
            using ( Mocks.Playback() )
            {
                presenter.DisplayMonster();
            }
        }

        [Test]
        public void SaveMonsterSendsTheDataOnTheViewToTheRepository()
        {
            IMonsterRepository monsterRepository = Mocks.StrictMock<IMonsterRepository>();
            IMonsterView monsterView = Mocks.StrictMock<IMonsterView>();
            MonsterPresenter presenter = new MonsterPresenter(MONSTER_NAME, monsterView, monsterRepository);
            using ( Mocks.Record() )
            {
                RetrieveMonsterFromViewAndSave(monsterView, monsterRepository);
                LoadAndDisplayMonster(monsterView, monsterRepository);
            }
            using ( Mocks.Playback() )
            {
                presenter.SaveMonster();
            }
        }

        [SetUp]
        public void SetUp()
        {
            Mocks = new MockRepository();
            TestMonster();
        }

        private void LoadAndDisplayMonster(IMonsterView monsterView, IMonsterRepository monsterRepository)
        {
            ReadOnlyCollection<string> monsterNames = new ReadOnlyCollection<string>(new List<string> { MONSTER_NAME });
            Expect.Call(monsterRepository.GetAllNames()).Return(monsterNames);
            Expect.Call(monsterRepository.GetByName(MONSTER_NAME)).Return(_monster);
            monsterView.MonsterName = _monster.Name;
            monsterView.Level = _monster.Level;
            monsterView.Role = _monster.Role;
            monsterView.Elite = _monster.Elite;
            monsterView.Leader = _monster.Leader;
            monsterView.Solo = _monster.Solo;
            monsterView.MonsterSize = _monster.CreatureSize;
            monsterView.Origin = _monster.Origin;
            monsterView.Keywords = _monster.Keywords;
            monsterView.HitPoints = _monster.HitPointsMaximum;
            monsterView.InitiativeModifier = _monster.InitiativeModifier;
            monsterView.ArmorClass = _monster.DefenseArmorClass;
            monsterView.FortitudeDefense = _monster.DefenseFortitude;
            monsterView.ReflexDefense = _monster.DefenseReflex;
            monsterView.WillpowerDefense = _monster.DefenseWillpower;
            monsterView.Perception = _monster.SensesPerception;
            monsterView.Senses = _monster.SensesOther;
            monsterView.Speed = _monster.MovementSpeed;
            monsterView.SpeedOther = _monster.MovementSpeedOther;
            monsterView.ActionPoints = _monster.ActionPoints;
            monsterView.SavingThrows = _monster.SavingThrows;
            monsterView.Strength = _monster.AbilityStrength;
            monsterView.Constitution = _monster.AbilityConstitution;
            monsterView.Dexterity = _monster.AbilityDexterity;
            monsterView.Intelligence = _monster.AbilityIntelligence;
            monsterView.Wisdom = _monster.AbilityWisdom;
            monsterView.Charisma = _monster.AbilityCharisma;
            monsterView.AttackPowers = _monster.AttackPowers;
            monsterView.SpecialQualities = _monster.SpecialQualities;
            monsterView.Tactics = _monster.Tactics;
            monsterView.Equipment = _monster.Equipment;
            monsterView.ExperiencePointValue = _monster.ExperiencePointValue;
        }

        private void RetrieveMonsterFromViewAndSave(IMonsterView monsterView, IMonsterRepository monsterRepository)
        {
            Expect.Call(monsterView.SaveAsName).Return(_monster.Name);
            Expect.Call(monsterView.Level).Return(_monster.Level);
            Expect.Call(monsterView.Role).Return(_monster.Role);
            Expect.Call(monsterView.Elite).Return(_monster.Elite);
            Expect.Call(monsterView.Leader).Return(_monster.Leader);
            Expect.Call(monsterView.Solo).Return(_monster.Solo);
            Expect.Call(monsterView.MonsterSize).Return(_monster.CreatureSize);
            Expect.Call(monsterView.Origin).Return(_monster.Origin);
            Expect.Call(monsterView.Keywords).Return(_monster.Keywords);
            Expect.Call(monsterView.HitPoints).Return(_monster.HitPointsMaximum);
            Expect.Call(monsterView.InitiativeModifier).Return(_monster.InitiativeModifier);
            Expect.Call(monsterView.ArmorClass).Return(_monster.DefenseArmorClass);
            Expect.Call(monsterView.FortitudeDefense).Return(_monster.DefenseFortitude);
            Expect.Call(monsterView.ReflexDefense).Return(_monster.DefenseReflex);
            Expect.Call(monsterView.WillpowerDefense).Return(_monster.DefenseWillpower);
            Expect.Call(monsterView.Perception).Return(_monster.SensesPerception);
            Expect.Call(monsterView.Speed).Return(_monster.MovementSpeed);
            Expect.Call(monsterView.SpeedOther).Return(_monster.MovementSpeedOther);
            Expect.Call(monsterView.ActionPoints).Return(_monster.ActionPoints);
            Expect.Call(monsterView.SavingThrows).Return(_monster.SavingThrows);
            Expect.Call(monsterView.Strength).Return(_monster.AbilityStrength);
            Expect.Call(monsterView.Constitution).Return(_monster.AbilityConstitution);
            Expect.Call(monsterView.Dexterity).Return(_monster.AbilityDexterity);
            Expect.Call(monsterView.Intelligence).Return(_monster.AbilityIntelligence);
            Expect.Call(monsterView.Wisdom).Return(_monster.AbilityWisdom);
            Expect.Call(monsterView.Charisma).Return(_monster.AbilityCharisma);
            Expect.Call(monsterView.AttackPowers).Return(_monster.AttackPowers);
            Expect.Call(monsterView.SpecialQualities).Return(_monster.SpecialQualities);
            Expect.Call(monsterView.Tactics).Return(_monster.Tactics);
            Expect.Call(monsterView.Equipment).Return(_monster.Equipment);
            monsterRepository.Save(_monster);
        }

        private void TestMonster()
        {
            _monster = DefaultTestObjects.TestMonster();
            _monster.Name = MONSTER_NAME;
            _monster.Level = 4;
            _monster.Role = MonsterRole.Controller;
            _monster.Elite = true;
            _monster.Leader = true;
            _monster.Solo = false;
            _monster.CreatureSize = CreatureSize.Large;
            _monster.Origin = "Fey";
            _monster.Keywords = "Incorporeal, Yellow";
            _monster.HitPointsMaximum = 30;
            _monster.InitiativeModifier = 3;
            _monster.DefenseArmorClass = 20;
            _monster.DefenseFortitude = 18;
            _monster.DefenseReflex = 17;
            _monster.DefenseWillpower = 19;
            _monster.SensesPerception = 12;
            _monster.SensesOther = "Darkvision";
            _monster.MovementSpeed = 6;
            _monster.MovementSpeedOther = "Fly 6";
            _monster.ActionPoints = 1;
            _monster.SavingThrows = 2;
            _monster.AbilityStrength = 16;
            _monster.AbilityConstitution = 15;
            _monster.AbilityDexterity = 14;
            _monster.AbilityIntelligence = 13;
            _monster.AbilityWisdom = 12;
            _monster.AbilityCharisma = 11;
            _monster.AttackPowers = "Longsword";
            _monster.SpecialQualities = "Resist cold 5";
            _monster.Tactics = "It kills you";
            _monster.Equipment = "Longsword, Chainmail";
        }
    }
}